내 타입스크립트 코드가 이렇게 느릴 리 없어

📅 2024. 11. 21

2024 당근 테크 밋업에서 김은수님이 발표한 타입 추론 성능 개선 사례를 정리했습니다. VSCode의 타입 추론 빨간줄이 너무 늦게 뜨는 문제를 쫓다가 타입 체크 성능 개선까지 이르게 되었다고 합니다. 개인적으로 자바스크립트 번들 크기 개선 사례는 많이 들어봤지만 타입스크립트 성능 개선 사례는 처음이라 흥미로웠습니다. 타입스크립트 성능을 측정하는 방법부터 개선하는 방법까지 핵심만 요약해서 정리해보았습니다.

  • VSCode 재시작 후, 타입 체크가 끝날 때까지(빨간줄이 표시될 때까지) 6초가 걸림
  • TypeScript 공식 문서에서 성능 진단 및 분석 방법을 알게됨
  • tsc --extendedDiagnostics --generateTrace ./traces을 실행하여 컴파일 소요 시간을 출력하고 컴파일 과정의 자세한 추적 데이터를 생성할 수 있음
  • 생성된 추적 데이터를 TypeScript 팀에서 제공하는 분석 도구인 @typescript/analyze-trace로 분석해봄
    • npx analyze-trace ./traces
  • 분석 결과, styled로 wrap된 컴포넌트들이 핫스팟으로 선정
  • 구글에서 만든 Event Trace 분석 도구인 perfetto를 이용하여 데이터를 분석해봄
    • https://ui.perfetto.dev 사이트에 --generateTrace로 출력된 파일을 업로드하면 분석 결과를 시각화해서 보여줌
  • 타입 추론이 가장 오래 걸리는 지점을 확인하기 위해 가장 긴 초록색 블록(타입 체킹 단계)을 찾아봄
    • 초록색 블록의 sourceId, targetId를 확인 -> types.json에서 type의 id를 확인
  • 분석 결과, Polymorphic React 컴포넌트인 Flex 컴포넌트의 as 타입이 원인
  • as prop에 사용되는 keyof JSX.IntrinsicElements는 175개의 union type으로 정의되어 타입 추론을 느리게 만듬
  • 타입 체킹 시칸을 단축하기 위해 두 가지 방법을 사용
  • 첫 번째는 타입 좁히기

As-is

type Elements = keyof JSX.IntrinsicElements;

To-be

type Elements = 'div' | 'section' | 'label';
  • 두 번째는 동적 타입 추론
    • Generic을 사용하여 런타임 입력값을 바탕으로 타입을 추론하도록 수정함
    • ElementType을 직접 정의하는 대신 React에서 제공하는 ElementType을 사용하도록 수정함
  • 두 가지 방법을 통해 최종적으로 타입 체킹 시간을 42초 -> 11초(-73%)로 단축
  • 꿀팁: 타입스크립트 Wiki에서 권장하는 컴파일 최적화 코드 작성법 4가지 소개
    • Preferring Interfaces Over Intersections (가능하면 인터섹션보다 인터페이스 사용하기)
    • Using Type Annotations (타입 어노테이션을 붙여라)
    • Preferring Base Types Over Unions (가능하면 유니온보다 기본 타입 사용하기)
    • Naming Complex Types (복잡한 타입엔 이름을 지어라)
  • 발표자분이 실제로 Naming Complex Types 사례를 활용하여 Zod의 타입 체킹 시간을 0.31초 -> 0.32초(-36%) 단축함